#pragma once
#include <iostream>
#include <memory>
#include <unordered_map>
#include <functional>
#include "Epoller.hpp"
#include "Connection.hpp"

namespace wxd
{

    class Reactor // 反应堆-事件派发器
    {
        static const int ready_events_num = 256;
        using connection_ptr_t = std::shared_ptr<Connection>;

    public:
        // 创建epoll模型
        Reactor()
            : _epoller_ptr(std::make_unique<Epoller>()), _is_running(false)
        {
        }
        // 插入连接到Reactor的unordered_map
        bool InsertConnection(connection_ptr_t connection_ptr)
        {
            // 插入-文件描述符合法插入
            if (connection_ptr->Sockfd() > 0)
            {
                // 插入到unordered_map
                _connections.insert(std::make_pair(connection_ptr->Sockfd(), connection_ptr));

                // 写入到内核
                int ret = _epoller_ptr->Add(connection_ptr->Sockfd(), connection_ptr->GetEvents());

                if (ret > 0)
                    LOG(LogLevel::INFO) << "InsertConnection Success! fd = " << connection_ptr->Sockfd();

                // 设置回指的指针
                connection_ptr->SetOwner(this);
            }
            return false;
        }

        bool ConnectIsExist(int fd)
        {
            auto it = _connections.find(fd);
            return it != _connections.end();
        }
        void DelateConnection(int sockfd)
        {
            
            if(ConnectIsExist(sockfd))            
            {
                //从epoll模型中删除（从内核中删除）
                _epoller_ptr->Del(sockfd);

                //关闭文件描述符
                _connections[sockfd]->Close();

                //从unordered_map 中删除
                _connections.erase(sockfd);
            }
        }
        void ModifyConnection(int sockfd,bool enable_read,bool enable_write,bool enable_except)    
        {
            _epoller_ptr->Mod(sockfd,enable_read,enable_write,enable_except);
        }

        // 派发事件
        void Dispatcher(int num)
        {
            for (int i = 0; i < num; i++)
            {
                int fd = _ready_events[i].data.fd;
                // LOG(LogLevel::DEBUG) << fd;
                uint32_t events = _ready_events[i].events;

                // 读事件就绪
                if (events & EPOLLIN)
                {
                    // 派发读任务
                     LOG(LogLevel::DEBUG) << "fd "<<fd<<" 读事件就绪";
                    _connections[fd]->Recv();
                }
                // 写事件就绪
                if (events & EPOLLOUT)
                {
                    // 派发写任务
                    LOG(LogLevel::DEBUG) << "fd "<<fd<<" 写事件就绪";
                    _connections[fd]->Send();
                }
                // 异常事件就绪
                if ((events & EPOLLERR) || (events & EPOLLHUP))
                {
                    LOG(LogLevel::DEBUG) << "fd "<<fd<<" 异常就绪";

                    // 转成读写事件
                    _connections[fd]->SetEvents(EPOLLIN | EPOLLOUT);
                }
            }
        }

        void OnceLoop(int timeout)
        {
            // 循环等待
            int num = _epoller_ptr->Wait(_ready_events, ready_events_num, timeout);
            if (num < 0)
                return;
            else if (num == 0)
            {
                LOG(LogLevel::INFO) << "time out...";
            }
            else
            {
                // 派发事件
                LOG(LogLevel::INFO) << "有新事件就绪！";
                Dispatcher(num);
            }
        }

        void PrintDebugInfo()
        {
            LOG(LogLevel::DEBUG)<< "epoll当前管理的fd：";
            for(auto it = _connections.begin();it != _connections.end();it++)
            {
                std::cout<<it->first<<" ";
            }
            std::cout<<std::endl;
        }

        // Loop
        void Start()
        {
            _is_running = true;
            int timeout = 1000;
            while (_is_running)
            {
                PrintDebugInfo();
                OnceLoop(timeout);                
            }
            _is_running = false;
        }

        void Stop()
        {
            _is_running = false;
        }

    private:
        std::unique_ptr<Epoller> _epoller_ptr;                  // 管理的epoll模型
        std::unordered_map<int, connection_ptr_t> _connections; // 管理所有的连接，以fd为键值
        struct epoll_event _ready_events[ready_events_num];     // 可以设置为可变的，暂设置为固定的
        bool _is_running;
    };
}